//Copyright (C) 2013 Julio Espindola
//
//This file is part of VSize Checkers.
//
//VSize Checkers is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//VSize Checkers is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with VSize Checkers.  If not, see <http://www.gnu.org/licenses/>.

package checkers;

import java.util.ArrayList;

class Queen extends Piece
{       
    Queen(byte color)
    {
        super(color);
    }
    
    private Jump findJumpOnDiag(Board b, MJumps jumps, int square, int dir)
    {
        Jump j = null;
        int current = b.getIndex(square, dir);
        while(current != -1)
        {
            if(!b.isFree(current))
            {
                if(b.jumpable(current, dir, color) && !jumps.alreadyJumped(current))
                    j = new Jump(square, b.getIndex(current, dir), current, b.getSquare(current));
                break;
            }  
            
            current = b.getIndex(current, dir);
        }
        return j;
    }
    
    @Override
    protected ArrayList<Move> getMoves(Board b, int square)
    {
        ArrayList<Move> moves = new ArrayList<Move>(20);
        ArrayList<Integer> free = new ArrayList<Integer>(20);
        
        for(int i=0; i<=Board.NUM_DIR; ++i)
            free.addAll(getFreeSquaresOnDiag(b, square, i));
        
        for(int i=0; i<free.size(); ++i)
            moves.add(new Move(square, free.get(i)));
        
        return moves;
    }
    
    private ArrayList<Integer> getFreeSquaresOnDiag(Board b, int square, int dir)
    {
        ArrayList<Integer> moves = new ArrayList<Integer>(10);
        int current = b.getIndex(square, dir);

        while(current != -1 && b.isFree(current))
        {
            moves.add(current);
            current  = b.getIndex(current, dir);
        }
        
        return moves;
    }
    
    @Override
    protected void getJumps(Board b, int square, ArrayList<Move> arr, MJumps jumps)
    {
        ArrayList<Jump> moves = new ArrayList<Jump>(4);
        for(int i=0; i<=Board.NUM_DIR; ++i)
            moves.add(findJumpOnDiag(b, jumps, square, i));
        
        for(int i=0; i<moves.size(); ++i)
        {
            Jump move = moves.get(i);
            if(move != null)
            {
                move.make(b);
                jumps.addJump(move);
                getJumps(b, move.dest, arr, jumps, i);
                jumps.removeJump();
                move.undo(b);
            }
        }
    }
    


    private void getJumps(Board b, int square, ArrayList<Move> arr, MJumps jumps, int dir)
    {
        byte piece = b.getPiece(square);
        boolean capture = false;
        int current = square;
        int last;
        int oppDir = Board.NUM_DIR - dir;
        Jump j = findJumpOnDiag(b, jumps, square, dir);

        if(j != null)
        {
            capture = true;
            j.make(b);
            jumps.addJump(j);
            getJumps(b, j.dest, arr, jumps, dir);
            jumps.removeJump();
            j.undo(b);
        }
        
        for(;;)
        {
            for(int i=0; i<=Board.NUM_DIR; ++i)
            {
                if(i == dir || i == oppDir) continue;
                
                j = findJumpOnDiag(b, jumps, current, i);
                if(j != null)
                {
                    capture = true;
                    Jump newJump = new Jump(current, jumps.popJump());
                    jumps.addJump(newJump);
                    
                    j.make(b);
                    jumps.addJump(j);
                    getJumps(b, j.dest, arr, jumps, i);
                    jumps.removeJump();
                    j.undo(b);
                }
            }
            
            last = current;
            current = b.getIndex(current, dir);
            if(current == -1 || !b.isFree(current))
            {
                b.setPiece(last, EMPTY);
                b.setPiece(square, piece);
                break;
            }
            b.setPiece(current, piece);
            b.setPiece(last, EMPTY);
        }
        
        if(!capture)
        {
            if(jumps.jumps.size() > maxSize) maxSize = jumps.jumps.size();
            arr.add(new MJumps(square, jumps));   
            ArrayList<Integer> free = getFreeSquaresOnDiag(b, square, dir);
            
            for(int i=0; i<free.size(); ++i)
            {
                Jump newJump = new Jump(free.get(i), jumps.popJump());
                jumps.addJump(newJump);
                arr.add(new MJumps(free.get(i), jumps));
            }
        }
    }
    
}
